package com.abel.bigwater.dataserver.model.qdies

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.dataserver.model.PacketCmdException
import io.netty.buffer.ByteBuf

open class DtenAsk485ConfigData(_len: Int) : D10BaseData(_len) {
    override var type = FuncType.Ask485Config

    var internalAddr: Byte? = null

    /**
     * 485总线地址 8字节 不足补零
    01补为01 00 00 00 00 00 00 00
     */
    var addr485: Long? = null

    var proto = ProtoType.Meter485_188

    var baud = BaudRateType.Baud2400

    var bit = BitType.Bit8

    var stopbit = StopbitType.Stopbit1

    var check = CheckType.None

    var readMode = ReadModeType.DayMode

    /**
     * 上传时刻 2字节 两个字节分别代表星期， 小时
    的BCD码
     */
    var uploadStart: BcdString? = null

    var samplePeriod: Int = 0

    var uploadPeriod: Short = 0

    /**
     * 供电电压 1字节 单位:V， 取值范围5--24
     */
    var volt: Short? = null

    override fun fill(buf: ByteBuf) {
        assert(internalAddr != null && addr485 != null && uploadStart?.size == 2)
        buf.apply {
            writeByte(internalAddr!!.toInt())
            writeLong(addr485!!)
            writeByte(proto.code).writeByte(baud.code).writeByte(bit.code).writeByte(stopbit.code).writeByte(check.code)

            writeByte(readMode.code.toInt())
            writeBytes(uploadStart!!.hexArray)
            writeShort(samplePeriod!!)
            writeByte(uploadPeriod!!.toInt())
            writeByte(volt!!.toInt())
        }
    }

    override fun parse(buf: ByteBuf): Boolean {
        buf.apply {
            internalAddr = readByte()
            addr485 = readLong()

            proto = ProtoType.values().find { it.code == readByte().toInt() }!!

            val b1v = readByte().toInt()
            val b1 = BaudRateType.values().find { it.code == b1v } ?: throw PacketCmdException("invalid baud: $b1v")
            baud = b1

            bit = BitType.values().find { it.code == readByte().toInt() }!!
            stopbit = StopbitType.values().find { it.code == readByte().toInt() }!!

            val c1v = readByte().toInt()
            val c1 = CheckType.values().find { it.code == c1v } ?: throw PacketCmdException("invalid check: $c1v")
            check = c1

            val r1v = readByte()
            val r1 = ReadModeType.values().find { it.code == r1v }
                    ?: throw PacketCmdException("invalid read-mode: $r1v")
            readMode = r1

            uploadStart = BcdString.create(this, 2)
            samplePeriod = readUnsignedShort()
            uploadPeriod = readUnsignedByte()

            volt = readUnsignedByte()
        }

        return true
    }

    override fun count(): Int = MIN_LEN

    companion object {
        const val MIN_LEN = 1 + 8 + 5 + 1 + 2 + 2 + 1 + 1
    }
}

/**
 * 规约号 1字节 1： 485 大表 188 规约（默认）
2： 485 大表 645 规约
3： 485 大表 MODBUS 规约
4： 天线 1.3
5： 苍南
6： 新科
7： 鸿鹄卡表 1
8： 鸿鹄卡表 2
9： 鸿鹄卡表 3
 */
enum class ProtoType(val code: Int) {
    Meter485_188(1),
    Meter485_645(2),
    Meter485Modbus(3),

    Artena(4),

    Cangnan(5),

    Xinke(6),

    Honghu1(7),
    Honghu2(8),
    Honghu3(9)
}

/**
 * 波特率 1字节 1:2400（默认）
2:4800
3:9600
4:19200
 */
enum class BaudRateType(val code: Int, val rate: Int) {
    Baud2400(1, 2400),

    Baud4800(2, 4800),

    Baud9600(3, 9600),

    Baud19200(4, 19200)
}

/**
 * 数据位 1字节 1:8 （默认）
2:7
3:6
 */
enum class BitType(val code: Int, val bit: Int) {
    Bit8(1, 8),

    Bit7(2, 7),

    Bit6(3, 6)
}

/**
 * 停止位 1字节 1:1 （默认）
2:2
 */
enum class StopbitType(val code: Int, val bit: Int) {
    Stopbit1(1, 1),
    Stopbit2(2, 2)
}

/**
 * 校验位 1字节 1： 偶校验
2： 奇校验
3： 无校验 （默认）
 */
enum class CheckType(val code: Int) {
    Even(1),
    Odd(2),
    None(3)
}